local dbg = require 'jass.debug'
local jass = require 'jass.common'

local GROUP = jass.CreateGroup()

local class = { }
setmetatable(class,class)
ac.selector.class['unit'] = class

-- 范围选择
class['range'] = function(self,info)
    local p = self._point:get_point()
    local r = self._range
    local x,y = p:get()
    jass.GroupEnumUnitsInRange(GROUP, x, y, r + 256, nil)
    while true do
        local h = jass.FirstOfGroup(GROUP)
        if h and h ~= 0 then
            jass.GroupRemoveUnit(GROUP, h)
            local u = ac.unit(h)
            if u and u:in_range(p, r) and self:do_filter(u) then 
                table.insert(info,u)
            end
        else
            break
        end 
    end
end

-- 扇形选择
class['sector'] = function(self,info)
    local p = self._point:get_point() 
    local x,y = p:get()
    local r = self._range
    local a = self._angle 
    local s = self.section / 2 
    jass.GroupEnumUnitsInRange(GROUP, x, y, r + 256, nil)
    while true do 
        local h = jass.FirstOfGroup(GROUP)
        if h and h ~= 0 then
            jass.GroupRemoveUnit(GROUP, h)
            local u = ac.unit(h)
            if u and u:in_range(p, r) and ac.math_angle(a,p / u:get_point()) <= s and self:do_filter(u) then 
                table.insert(info,u)
            end
        else
            break
        end 
    end 
end 

-- 矩形选择
class['rect'] = function(self,info)
    local rct = ac.rect.j_temp(self._rect)
    jass.GroupEnumUnitsInRect(GROUP, rct, nil)
    while true do
        local h = jass.FirstOfGroup(GROUP)
        if h and h ~= 0 then
            jass.GroupRemoveUnit(GROUP, h)
            local u = ac.unit(h)
            if u and self:do_filter(u) then 
                table.insert(info,u)
            end
        else
            break
        end 
    end
end
 
-- 直线选择
class['line'] = function(self,info)
    local s = self._point:get_point() 
    local t = s - {self._angle, self._len}
    local x1, y1 = s:get()
    local x2, y2 = t:get()
    local a, b = y1 - y2, x2 - x1
    local c = - a * x1 - b * y1
    local l = (a * a + b * b) ^ 0.5
    local w = self._width / 2
    local r = self._len / 2
    local x, y = (x1 + x2) / 2, (y1 + y2) / 2
    local p = ac.point(x, y)
    jass.GroupEnumUnitsInRange(GROUP, x, y, r + 256, nil)
    while true do
        local h = jass.FirstOfGroup(GROUP)
        if h and h ~= 0 then
            jass.GroupRemoveUnit(GROUP, h)
            local u = ac.unit(h)
            if u and u:in_range(p, r) then
                local x, y = u:get_point():get()
                local d = math.abs(a * x + b * y + c) / l
                if d <= w + u:get_selected_radius() and self:do_filter(u) then
                    table.insert(info,u)
                end
            end
        else
            break
        end
    end
end

-- 依托玩家选择
class['player'] = function(self,info)
    local p = self._player
    jass.GroupEnumUnitsOfPlayer(GROUP, p.handle, nil)
    while true do
        local h = jass.FirstOfGroup(GROUP)
        if h and h ~= 0 then
            jass.GroupRemoveUnit(GROUP, h)
            local u = ac.unit(h)
            if u and self:do_filter(u) then 
                table.insert(info,u)
            end
        else
            break
        end 
    end
end

local mt = { }
class.__index = mt 
extends(ac.selector)(mt)

-- 选取玩家的单位
-- @param player 玩家
function mt:player(player)
    if not self._type then 
        self._type = 'player'
    end 
    self._player = player 
    return self 
end 

-- 商店单位
function mt:is_store()
    return self:filter(function(dest)
        return dest:is_store()
    end)
end

-- 不在表里
function mt:out(info)
    return self:filter(function(dest)
        return not info[dest]
    end)
end 

-- -- 可以是敌人
-- function mt:can_enemy(target)
--     return self:filter(function(dest)
--         return dest:is_enemy(target)
--     end)
-- end 

-- -- 可以是友军
-- function mt:can_ally(target)
--     return self:filter(function(dest)
--         return dest:is_ally(target)
--     end)
-- end 

-- -- 可以是中立
-- function mt:can_neutral(target)
--     return self:filter(function(dest)
--         return dest:is_neutral(target)
--     end)
-- end 

-- 是敌人
function mt:enemy(target)
    return self:filter(function(dest)
        return dest:is_enemy(target)
    end)
end 

-- 是友军
function mt:ally(target)
    return self:filter(function(dest)
        return dest:is_ally(target)
    end)
end 

-- 是中立
function mt:neutral(target)
    return self:filter(function(dest)
        return dest:is_neutral(target)
    end)
end 

-- 是盟友
function mt:league(target)
    return self:filter(function(dest)
        return dest:is_league(target)
    end)
end 

-- 不是盟友
function mt:unleague(target)
    return self:filter(function(dest)
        return not (dest:is_league(target))
    end)
end 

-- 不能是守卫
function mt:not_ward()
    return self:filter(function(dest)
        return not dest:is_ward() 
    end)
end 

-- 必须是守卫
function mt:must_ward()
    return self:filter(function(dest)
        return dest:is_ward()
    end)
end 

-- 不能是古树
function mt:not_ancient()
    return self:filter(function(dest)
        return not dest:is_ancient() 
    end)
end 

-- 必须是古树
function mt:must_ancient()
    return self:filter(function(dest)
        return dest:is_ancient()
    end)
end 

-- 必须是英雄
function mt:must_hero()
    return self:filter(function(dest)
        return dest:is_hero()
    end)
end

-- 不能是英雄
function mt:not_hero()
    return self:filter(function(dest)
        return not dest:is_hero() 
    end)
end 

-- 必须是建筑
function mt:must_build()
    return self:filter(function(dest)
        return dest:is_build()
    end)
end 

-- 不能是建筑
function mt:not_build()
    return self:filter(function(dest)
        return not dest:is_build()
    end)
end 

-- 是地面
function mt:is_ground()
    return self:filter(function(dest)
        return dest:is_ground()
    end)
end

-- 可见的
function mt:visible(player)
    return self:filter(function(dest)
        return dest:is_visible(player)
    end)
end 

-- 指定类别
function mt:is_type(name)
    return self:filter(function(dest)
        return dest:is_type(name)
    end)
end 

-- 不指定类别
function mt:not_type(name)
    return self:filter(function(dest)
        return not dest:is_type(name)
    end)
end 

-- 指定类型
function mt:id(name)
    self._name = name
    return self
end 

-- 队伍要求
function mt:team(name)
    self._team = name
    return self
end 

-- 可以是无敌
function mt:can_god()
    self._god = true
    return self
end 

-- 可以是死亡的
function mt:can_dead()
    self._dead = true 
    return self
end 

-- 可以是装载的
function mt:can_loaded()
    self._loaded = true
    return self
end 

-- 不可选取也强制选
function mt:can_shield()
    self._shield = true 
    return self
end 

-- 选取
function mt:select()
    local name = self._type 
    if name and class[name] then 
        local info = { }
        class[name](self,info)
        return info
    end 
end

-- 过滤
function mt:do_filter(u)
    if not u:is_can_selector() and not self._shield then 
        return false 
    end 
    if not self._god and (u:has_restriction '无敌' or u:has_restriction "伪无敌") then 
        return false 
    end 
    if not self._dead and not u:is_alive() then 
        return false 
    end 
    if self._player and u:get_owner() ~= self._player then 
        return false 
    end 
    if self._id and u:get_id() ~= self._id then 
        return false 
    end 
    if self._team and u:get_owner().team ~= self._team then 
        return false 
    end 
    return ac.selector.do_filter(self,u)
end 

return class 